package org.visionlibrary.image.filters.edge;

import javax.media.jai.TiledImage;

import org.visionlibrary.image.acquisition.ImageFactory;
import org.visionlibrary.image.model.AbstractFilter;
import org.visionlibrary.image.model.ConvolutionKernel;
import org.visionlibrary.image.model.KernelFilter;


//Obliczany jest gradient dla kazdego z kerneli: Gx i Gy pozniej obliczana jest
//wspolna wartosc G = pierwiastek(Gx^2 + Gy^2);
public abstract class TwoKernelEdgeDetector extends AbstractFilter {
	protected ConvolutionKernel horKernel;
	protected ConvolutionKernel verKernel;
	
	public ConvolutionKernel getHorizontalKernel() {
		return horKernel;
	}

	public ConvolutionKernel getVerticalKernel() {
		return verKernel;
	}

	protected void setHorizontalKernel(ConvolutionKernel kernel) {
		if(null == kernel)
			throw new NullPointerException("Horizontal kernel is null.");
		
		horKernel = kernel;
	}

	protected void setVerticalKernel(ConvolutionKernel kernel) {
		if(null == kernel)
			throw new NullPointerException("Vertical kernel is null.");
		
		verKernel = kernel;
	}

	public TiledImage applyFilter(TiledImage src, TiledImage dest) {
		if (null == src)
			throw new NullPointerException("Source image is null.");

		if (null == dest)
			dest = (new ImageFactory()).createCompatibleImage(src);
		
		ImageFactory ifactory = new ImageFactory();
		
		TiledImage dest1 = ifactory.createCompatibleImage(src);
		TiledImage dest2 = ifactory.createCompatibleImage(src);

		KernelFilter kf = new KernelFilter();
		kf.setKernel(verKernel);
		kf.applyFilter(src, dest1);
		kf.setKernel(horKernel);
		kf.applyFilter(src, dest2);

		int maxX = src.getWidth();
		int maxY = src.getHeight();
		for (int ch = 0; ch < src.getNumBands(); ch++)
			for (int x = 0; x < maxX; x++)
				for (int y = 0; y < maxY; y++) {
					int Gx = dest1.getSample(x, y, ch);
					int Gy = dest2.getSample(x, y, ch);
					int G = ((int) Math.sqrt(Gx * Gx + Gy * Gy));
					dest.setSample(x, y, ch, G);
				}

		return dest;
	}
}
